---
id: code-generation
title: Code Generation
sidebar_label: Code Generation
hide_title: true
description: 'RTK Query > Usage > Code Generation: automated creation of API code'
---

&nbsp;

# Code Generation

RTK Query's API and architecture is oriented around declaring API endpoints up front. This lends itself well to automatically generating API slice definitions from external API schema definitions, such as OpenAPI and GraphQL.

We have early previews of code generation capabilities available as separate tools.

## GraphQL

We provide a [Plugin for GraphQL Codegen](https://www.graphql-code-generator.com/docs/plugins/typescript-rtk-query). You can find the documentation to that on the graphql-codegen homepage.

For a full example on how to use it, you can see [this example project](https://github.com/reduxjs/redux-toolkit/tree/master/examples/query/react/graphql-codegen).

## OpenAPI

We provide a package for RTK Query code generation from OpenAPI schemas. It is published as `@rtk-query/codegen-openapi` and you can find the source code at [`packages/rtk-query-codegen-openapi`](https://github.com/reduxjs/redux-toolkit/tree/master/packages/rtk-query-codegen-openapi).

### Usage

Create an empty api using `createApi` like

```ts no-transpile title="src/store/emptyApi.ts"
// Or from '@reduxjs/toolkit/query' if not using the auto-generated hooks
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

// initialize an empty api service that we'll inject endpoints into later as needed
export const emptySplitApi = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: '/' }),
  endpoints: () => ({}),
})
```

Generate a config file (json, js or ts) with contents like

```ts no-transpile title="openapi-config.ts"
import type { ConfigFile } from '@rtk-query/codegen-openapi'

const config: ConfigFile = {
  schemaFile: 'https://petstore3.swagger.io/api/v3/openapi.json',
  apiFile: './src/store/emptyApi.ts',
  apiImport: 'emptySplitApi',
  outputFile: './src/store/petApi.ts',
  exportName: 'petApi',
  hooks: true,
}

export default config
```

and then call the code generator:

```bash
npx @rtk-query/codegen-openapi openapi-config.ts
```

#### Generating tags

If your OpenAPI specification uses [tags](https://swagger.io/docs/specification/grouping-operations-with-tags/), you can specify the `tag` option to the codegen.
That will result in all generated endpoints having `providesTags`/`invalidatesTags` declarations for the `tags` of their respective operation definition.

Note that this will only result in string tags with no ids, so it might lead to scenarios where too much is invalidated and unnecessary requests are made on mutation.

In that case you have two options:

1. Use [`endpointOverrides`](#overriding-tags) to customize tags for specific endpoints during code generation
2. Use [`enhanceEndpoints`](../api/created-api/code-splitting.mdx) after generation to manually add more specific `providesTags`/`invalidatesTags` with IDs

### Programmatic usage

```ts no-transpile title="src/store/petApi.ts"
import { generateEndpoints } from '@rtk-query/codegen-openapi'

const api = await generateEndpoints({
  apiFile: './fixtures/emptyApi.ts',
  schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
  filterEndpoints: ['getPetById', 'addPet'],
  hooks: true,
})
```

#### With Node.js Child process

```ts no-transpile title="bin/openapi-codegen.ts"
import { exec } from 'node:child_process'

const cliPath = require.resolve('@rtk-query/codegen-openapi/cli')

// you can also use esbuild-runner (esr) or ts-node instead of tsx
exec(`tsx ${cliPath} config.ts`)
```

### Config file options

#### Simple usage

```ts no-transpile
interface SimpleUsage {
  apiFile: string
  schemaFile: string
  apiImport?: string
  exportName?: string
  argSuffix?: string
  operationNameSuffix?: string
  responseSuffix?: string
  hooks?:
    | boolean
    | { queries: boolean; lazyQueries: boolean; mutations: boolean }
  tag?: boolean
  outputFile: string
  filterEndpoints?:
    | string
    | RegExp
    | EndpointMatcherFunction
    | Array<string | RegExp | EndpointMatcherFunction>
  endpointOverrides?: EndpointOverrides[]
  flattenArg?: boolean
}

export type EndpointOverrides = {
  pattern: EndpointMatcher
} & AtLeastOneOf<{
  type: 'mutation' | 'query'
  parameterFilter: ParameterMatcher
  providesTags: string[]
  invalidatesTags: string[]
}>
  useEnumType?: boolean
  outputRegexConstants?: boolean
  httpResolverOptions?: SwaggerParser.HTTPResolverOptions
}

export type EndpointMatcherFunction = (
  operationName: string,
  operationDefinition: OperationDefinition,
) => boolean
```

#### Filtering endpoints

If you only want to include a few endpoints, you can use the `filterEndpoints` config option to filter your endpoints.
Note that endpoints are transformed to camel case. For example, `login_user` will become `loginUser`.
`filterEndpoints` will be checked against this camel case version of the endpoint.

```ts no-transpile title="openapi-config.ts"
const filteredConfig: ConfigFile = {
  // ...
  // should only have endpoints loginUser, placeOrder, getOrderById, deleteOrder
  filterEndpoints: ['loginUser', /Order/],
}
```

#### Endpoint overrides

If an endpoint is generated as a mutation instead of a query or the other way round, you can override that:

```ts no-transpile title="openapi-config.ts"
const withOverride: ConfigFile = {
  // ...
  endpointOverrides: [
    {
      pattern: 'loginUser',
      type: 'mutation',
    },
  ],
}
```

You can also filter the parameters that are included for an endpoint, as long as they aren't a path parameter. This filter is of type `ParameterMatcher`. For example, to only include parameters that begin with "x-" for the 'loginUser' endpoint, see the below example.

```ts no-transpile title="openapi-config.ts"
const withOverride: ConfigFile = {
  // ...
  endpointOverrides: [
    {
      pattern: 'loginUser',
      parameterFilter: /^x-/,
    },
  ],
}
```

For more complex requirements, consider the other possible matchers, such as a `ParameterMatcherFunction`. The below example filters out any parameters that are in the header of the request.

```ts no-transpile title="openapi-config.ts"
const withOverride: ConfigFile = {
  // ...
  endpointOverrides: [
    {
      pattern: /.*/,
      parameterFilter: (_name, parameter) => parameter.in !== 'header',
    },
  ],
}
```

#### Overriding tags

You can override the `providesTags` and `invalidatesTags` generated for any endpoint, regardless of whether the global `tag` option is enabled:

```ts no-transpile title="openapi-config.ts"
const withTagOverrides: ConfigFile = {
  // ...
  tag: true, // or false - overrides work either way
  endpointOverrides: [
    {
      // Override the tags for a specific query
      pattern: 'getPetById',
      providesTags: ['SinglePet', 'PetDetails'],
    },
    {
      // Remove auto-generated tags by providing an empty array
      pattern: 'deletePet',
      invalidatesTags: [],
    },
    {
      // Add both providesTags AND invalidatesTags to any endpoint
      pattern: 'updatePet',
      providesTags: ['LastUpdatedPet'],
      invalidatesTags: ['Pet', 'PetList'],
    },
  ],
}
```

**Key behaviors:**

- Tag overrides take precedence over auto-generated tags from the OpenAPI `tags` field
- You can use an empty array (`[]`) to explicitly remove tags from an endpoint
- Both `providesTags` and `invalidatesTags` can be set on any endpoint type (query or mutation)
- Overrides work regardless of whether the global `tag: true` option is set

This is useful when:

- The OpenAPI tags don't match your caching strategy
- You need more specific cache invalidation than the default tag generation provides
- A mutation should also provide tags (e.g., login returning user data)
- A query should also invalidate tags (e.g., polling that triggers cache updates)

:::note
When using tag overrides with `tag: false`, the overridden tags will be emitted in the generated code, but they won't be automatically added to `addTagTypes`. You may need to manually add your custom tags to the base API's `tagTypes` array.
:::

#### Generating hooks

Setting `hooks: true` will generate `useQuery` and `useMutation` hook exports. If you also want `useLazyQuery` hooks generated or more granular control, you can also pass an object in the shape of: `{ queries: boolean; lazyQueries: boolean; mutations: boolean }`.

#### Generating regex constants for schema patterns

If your OpenAPI schema uses the [`pattern` keyword](https://swagger.io/docs/specification/data-models/data-types/#pattern) to specify regex validation on string properties, you can export these patterns as JavaScript regex constants by setting `outputRegexConstants: true`.

```ts no-transpile title="openapi-config.ts"
const config: ConfigFile = {
  schemaFile: 'https://petstore3.swagger.io/api/v3/openapi.json',
  apiFile: './src/store/emptyApi.ts',
  outputFile: './src/store/petApi.ts',
  outputRegexConstants: true,
}
```

For a schema with pattern-validated properties like:

```yaml
User:
  type: object
  properties:
    email:
      type: string
      pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    phone:
      type: string
      pattern: '^\+?[1-9]\d{1,14}$'
```

The codegen will generate:

```ts no-transpile title="Generated output"
export const userEmailPattern =
  /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
export const userPhonePattern = /^\+?[1-9]\d{1,14}$/
```

These constants can be used for client-side validation to ensure consistency with API expectations.

:::note
Only string-type properties with non-empty `pattern` values will generate constants. The constant name follows the format `{typeName}{propertyName}Pattern` in camelCase.
:::

#### Multiple output files

```ts no-transpile title="openapi-config.ts"
const config: ConfigFile = {
  schemaFile: 'https://petstore3.swagger.io/api/v3/openapi.json',
  apiFile: './src/store/emptyApi.ts',
  outputFiles: {
    './src/store/user.ts': {
      filterEndpoints: [/user/i],
    },
    './src/store/order.ts': {
      filterEndpoints: [/order/i],
    },
    './src/store/pet.ts': {
      filterEndpoints: [/pet/i],
    },
  },
}
```

#### Custom HTTP resolver options

If you need to customize the HTTP request issued to your server, you user the `httpResolverOptions` option. This object is passed directly to the `SwaggerParser` instance that fetches the OpenAPI schema.

For example, you can pass custom headers or set a custom request timeout.

```ts no-transpile title="openapi-config.ts"
const config: ConfigFile = {
  schemaFile: 'https://petstore3.swagger.io/api/v3/openapi.json',
  apiFile: './src/store/emptyApi.ts',
  outputFile: './src/store/petApi.ts',
  httpResolverOptions: {
    timeout: 30_000,
    headers: {
      Accept: 'application/json',
      Authorization: 'Basic cmVkdXgtdG9vbGtpdDppcy1ncmVhdA==',
    },
  },
}
```
